#include "Shader.h"

using namespace Gut;

bool ShaderFile::CreateFromFile(std::string path, int type)
{
	bool gr = true;

	std::ifstream ifs(path, std::ios::in);

	if (!ifs.is_open())
	{
		LOGI("cannot open file %s [path]", path.c_str());
		ifs.close();
		return false;
	}

	LOGI("Loading the file %s", path.c_str());

	std::string text = std::string((std::istreambuf_iterator<char>(ifs)),
		(std::istreambuf_iterator<char>()));

	gr = CreateFrom(text.c_str(), type);
	ifs.close();
    return gr;
}



bool Shader::CreateFromCode(const char* vcode, const char* fcode)
{
	ShaderFile vFile;
	ShaderFile fFile;

	GUT_FAILED(vFile.CreateFrom(vcode, GL_VERTEX_SHADER));
	GUT_FAILED(fFile.CreateFrom(fcode, GL_FRAGMENT_SHADER));

	this->ID = glCreateProgram();

	glAttachShader(this->ID, vFile.id);
	glAttachShader(this->ID, fFile.id);

	glLinkProgram(ID);

	return true;
}

bool Shader::CreateFromFile(ShaderFile vFile, ShaderFile fFile)
{
	this->ID = glCreateProgram();
	glAttachShader(this->ID, vFile.id);
	glAttachShader(this->ID, fFile.id);

	glLinkProgram(ID);
	return true;
}

bool Shader::CreateFromFilePath(std::string vPath, std::string fPath)
{
	bool gr;

	ShaderFile vFile;
	ShaderFile fFile;

	GUT_FAILED(vFile.CreateFromFile(vPath, GL_VERTEX_SHADER));
	GUT_FAILED(fFile.CreateFromFile(fPath, GL_FRAGMENT_SHADER));

	return CreateFromFile(vFile, fFile);

}

bool ShaderCode::CreateFrom(const char* code, int type)
{
	this->id = glCreateShader(type);
	glShaderSource(id, 1, &code, NULL);
	glCompileShader(id);
	if (!checkCompileErrors(id, GetShaderType(type)))
	{
		return false;
	}
	return true;
}

void ShaderCode::Release()
{
	glDeleteShader(this->id);
}

void Shader::Use() const
{
	glUseProgram(ID);
}

void Shader::Create()
{
	ID=glCreateProgram();
}

void Shader::Release()
{

	glDeleteProgram(this->ID);
}

void Shader::Link()
{
	glLinkProgram(ID);
}

void Shader::UnUse() const
{
	glUseProgram(0);
}

#ifdef WIN32

bool Shader::CreateFormFile(ShaderFile vFile, ShaderFile gFile, ShaderFile fFile)
{
	this->ID = glCreateProgram();
	glAttachShader(this->ID, vFile.id);
	glAttachShader(this->ID, gFile.id);
	glAttachShader(this->ID, fFile.id);
	glLinkProgram(ID);
	return true;
}

bool Shader::CreateFromFilePath(std::string vPath, std::string gPath, std::string fPath)
{

	ShaderFile vFile;
	ShaderFile gFile;
	ShaderFile fFile;

	GUT_FAILED(vFile.CreateFromFile(vPath, GL_VERTEX_SHADER));
	GUT_FAILED(gFile.CreateFromFile(gPath, GL_GEOMETRY_SHADER));
	GUT_FAILED(fFile.CreateFromFile(fPath, GL_FRAGMENT_SHADER));

	return CreateFormFile(vFile, gFile, fFile);
}
#endif // DEBUG

